package com.ruoyi.inventory.service.impl;

import java.util.List;
import java.util.Date;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Map;

import com.ruoyi.inventory.domain.dto.TWarehouseTransactionDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.BeanUtils;
import com.ruoyi.inventory.mapper.TWarehouseTransactionMapper;
import com.ruoyi.inventory.mapper.TWarehouseTransactionDTOMapper;
import com.ruoyi.inventory.mapper.TWarehouseTransactionItemMapper;
import com.ruoyi.inventory.domain.TWarehouseTransaction;
import com.ruoyi.inventory.domain.TWarehouseTransactionItem;
import com.ruoyi.inventory.domain.TWarehouseStock;
import com.ruoyi.inventory.service.ITWarehouseTransactionService;
import com.ruoyi.inventory.service.ITWarehouseStockService;
import com.ruoyi.common.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 出入库单(头)Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-24
 */
@Service
public class TWarehouseTransactionServiceImpl implements ITWarehouseTransactionService 
{
    private static final Logger logger = LoggerFactory.getLogger(TWarehouseTransactionServiceImpl.class);

    @Autowired
    private TWarehouseTransactionMapper tWarehouseTransactionMapper;
    
    @Autowired
    private TWarehouseTransactionDTOMapper tWarehouseTransactionDTOMapper;
    
    @Autowired
    private TWarehouseTransactionItemMapper tWarehouseTransactionItemMapper;
    
    @Autowired
    private ITWarehouseStockService tWarehouseStockService;

    /**
     * 查询出入库单(头)
     * 
     * @param txNo 出入库单(头)主键
     * @return 出入库单(头)
     */
    @Override
    public TWarehouseTransaction selectTWarehouseTransactionByTxNo(String txNo)
    {
        TWarehouseTransaction transaction = tWarehouseTransactionMapper.selectTWarehouseTransactionByTxNo(txNo);
        if (transaction != null) {
            // 查询交易明细
            TWarehouseTransactionItem itemQuery = new TWarehouseTransactionItem();
            itemQuery.setTxNo(txNo);
            List<TWarehouseTransactionItem> items = tWarehouseTransactionItemMapper.selectTWarehouseTransactionItemList(itemQuery);
            transaction.setTransactionItems(items);
        }
        return transaction;
    }

    /**
     * 查询出入库单(头)列表
     * 
     * @param tWarehouseTransaction 出入库单(头)
     * @return 出入库单(头)
     */
    @Override
    public List<TWarehouseTransaction> selectTWarehouseTransactionList(TWarehouseTransaction tWarehouseTransaction)
    {
        return tWarehouseTransactionMapper.selectTWarehouseTransactionList(tWarehouseTransaction);
    }

    /**
     * 查询出入库单(头)DTO列表
     * 
     * @param tWarehouseTransaction 出入库单(头)
     * @return 出入库单(头)DTO集合
     */
    @Override
    public List<TWarehouseTransactionDTO> selectTWarehouseTransactionDTOList(TWarehouseTransaction tWarehouseTransaction)
    {
        // 使用BeanUtils自动复制相同名称的属性
        TWarehouseTransactionDTO dto = new TWarehouseTransactionDTO();
        BeanUtils.copyProperties(tWarehouseTransaction, dto);
        
        // 使用DTOMapper查询，它会自动关联用户表获取昵称
        return tWarehouseTransactionDTOMapper.selectTWarehouseTransactionDTOList(dto);
    }

    /**
     * 新增出入库单(头)
     * 
     * @param tWarehouseTransaction 出入库单(头)
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTWarehouseTransaction(TWarehouseTransaction tWarehouseTransaction)
    {
        // 生成交易单号
        if (tWarehouseTransaction.getTxNo() == null || tWarehouseTransaction.getTxNo().isEmpty()) {
            String txNo = generateTxNo(tWarehouseTransaction.getTxType());
            tWarehouseTransaction.setTxNo(txNo);
        }
        
        // 设置操作人ID（当前登录用户）
        if (tWarehouseTransaction.getOperatorId() == null) {
            try {
                Long userId = SecurityUtils.getUserId();
                tWarehouseTransaction.setOperatorId(userId);
            } catch (Exception e) {
                // 如果获取用户ID失败，设置为默认值1（管理员）
                tWarehouseTransaction.setOperatorId(1L);
            }
        }
        
        // 设置创建时间和更新时间
        Date now = new Date();
        tWarehouseTransaction.setCreatedAt(now);
        tWarehouseTransaction.setUpdatedAt(now);
        
        // 设置默认值
        if (tWarehouseTransaction.getIsDelete() == null) {
            tWarehouseTransaction.setIsDelete(0);
        }
        
        // 插入交易主表
        int result = tWarehouseTransactionMapper.insertTWarehouseTransaction(tWarehouseTransaction);
        
        // 注意：交易明细的插入和库存更新将在控制器层处理
        // 这里只处理交易主表的插入
        
        return result;
    }
    
    /**
     * 新增完整的出入库单（包括明细和库存更新）
     * 
     * @param tWarehouseTransaction 出入库单(头)
     * @param partList 备件列表
     * @return 结果
     */
    @Transactional
    public int insertCompleteTransaction(TWarehouseTransaction tWarehouseTransaction, List<Object> partList) {
        logger.info("=== 开始完整交易创建 ===");
        logger.info("交易头信息: txNo={}, txType={}, warehouseCode={}", 
                tWarehouseTransaction.getTxNo(), tWarehouseTransaction.getTxType(), tWarehouseTransaction.getWarehouseCode());
        logger.info("partList大小: {}", partList != null ? partList.size() : 0);
        
        if (partList != null && !partList.isEmpty()) {
            logger.info("partList第一个元素: {}", partList.get(0));
        }
        
        // 先插入交易主表
        logger.info("步骤1: 插入交易主表");
        int result = insertTWarehouseTransaction(tWarehouseTransaction);
        logger.info("交易主表插入结果: {}", result);
        
        if (result <= 0) {
            logger.error("❌ 交易主表插入失败，无法继续");
            return 0;
        }
        
        // 如果有交易明细，需要插入明细并更新库存
        if (partList != null && !partList.isEmpty()) {
            logger.info("步骤2: 处理{}个交易明细", partList.size());
            
            for (int i = 0; i < partList.size(); i++) {
                try {
                    Object partObj = partList.get(i);
                    logger.info("处理第{}个备件明细: {}", i+1, partObj);
                    
                    // 将LinkedHashMap转换为Map来获取字段值
                    @SuppressWarnings("unchecked")
                    Map<String, Object> partMap = (Map<String, Object>) partObj;
                    
                    String partNo = (String) partMap.get("partNo");
                    Object quantityObj = partMap.get("quantity");
                    BigDecimal quantity;
                    
                    // 处理数量字段，前端可能传来Integer、Double或BigDecimal类型
                    if (quantityObj instanceof Integer) {
                        quantity = new BigDecimal((Integer) quantityObj);
                    } else if (quantityObj instanceof Double) {
                        quantity = new BigDecimal((Double) quantityObj);
                    } else if (quantityObj instanceof BigDecimal) {
                        quantity = (BigDecimal) quantityObj;
                    } else {
                        quantity = new BigDecimal(quantityObj.toString());
                    }
                    
                    logger.info("备件明细解析: partNo={}, quantity={}", partNo, quantity);
                    
                    // 出库时检查库存是否充足
                    if ("OUTBOUND".equals(tWarehouseTransaction.getTxType()) || "REPAIR".equals(tWarehouseTransaction.getTxType())) {
                        logger.info("出库检查库存充足性: warehouseCode={}, partNo={}, quantity={}", 
                                tWarehouseTransaction.getWarehouseCode(), partNo, quantity);
                        validateStockAvailability(tWarehouseTransaction.getWarehouseCode(), partNo, quantity);
                    }
                    
                    // 创建并插入交易明细记录
                    logger.info("步骤2.1: 插入交易明细记录");
                    TWarehouseTransactionItem transactionItem = new TWarehouseTransactionItem();
                    transactionItem.setTxNo(tWarehouseTransaction.getTxNo());
                    transactionItem.setPartNo(partNo);
                    transactionItem.setQuantity(quantity);
                    transactionItem.setDirection(tWarehouseTransaction.getTxType());
                    transactionItem.setRemark(tWarehouseTransaction.getRemark()); // 设置备注
                    transactionItem.setIsDelete(0);
                    
                    int itemResult = tWarehouseTransactionItemMapper.insertTWarehouseTransactionItem(transactionItem);
                    logger.info("交易明细插入结果: txNo={}, partNo={}, result={}", 
                            tWarehouseTransaction.getTxNo(), partNo, itemResult);
                    
                    if (itemResult > 0) {
                        // 更新库存
                        logger.info("步骤2.2: 更新库存 - 调用updateStock");
                        updateStock(tWarehouseTransaction.getWarehouseCode(), partNo, 
                                   quantity, tWarehouseTransaction.getTxType());
                        logger.info("✅ 库存更新完成: partNo={}, quantity={}", partNo, quantity);
                    } else {
                        logger.error("❌ 交易明细插入失败: partNo={}, result={}", partNo, itemResult);
                    }
                    
                } catch (Exception e) {
                    logger.error("处理备件明细时出错 [index={}]: {}", i, e.getMessage(), e);
                    // 继续处理其他明细，不中断整个事务
                    continue;
                }
            }
            logger.info("✅ 所有交易明细处理完成");
        } else {
            logger.warn("⚠️  无交易明细需要处理");
        }
        
        logger.info("=== 完整交易创建完成，txNo: {} ===", tWarehouseTransaction.getTxNo());
        return result;
    }
    
    /**
     * 生成交易单号
     * 
     * @param txType 交易类型
     * @return 交易单号
     */
    private String generateTxNo(String txType) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = sdf.format(new Date());
        String prefix = "INBOUND".equals(txType) ? "RK" : "CK"; // 入库RK，出库CK
        int randomNum = (int)(Math.random() * 1000);
        String txNo = prefix + timestamp + String.format("%03d", randomNum);
        logger.info("生成交易单号: txType={}, prefix={}, timestamp={}, random={}, txNo={}", 
                txType, prefix, timestamp, randomNum, txNo);
        return txNo;
    }
    
    /**
     * 验证出库时库存是否充足
     * 
     * @param warehouseCode 仓库编码
     * @param partNo 备件编号
     * @param outboundQuantity 出库数量
     * @throws RuntimeException 库存不足时抛出异常
     */
    private void validateStockAvailability(String warehouseCode, String partNo, BigDecimal outboundQuantity) {
        // 查询当前库存
        TWarehouseStock stockQuery = new TWarehouseStock();
        stockQuery.setWarehouseCode(warehouseCode);
        stockQuery.setPartNo(partNo);
        List<TWarehouseStock> stockList = tWarehouseStockService.selectTWarehouseStockList(stockQuery);
        
        BigDecimal currentStock = BigDecimal.ZERO;
        if (stockList != null && !stockList.isEmpty()) {
            currentStock = stockList.get(0).getQuantity();
        }
        
        // 检查库存是否充足
        if (currentStock.compareTo(outboundQuantity) < 0) {
            throw new RuntimeException(String.format("备件 %s 库存不足！当前库存：%s，出库数量：%s", 
                partNo, currentStock, outboundQuantity));
        }
    }
    
    /**
     * 更新库存 - 使用悲观锁
     * 
     * @param warehouseCode 仓库编码
     * @param partNo 备件编号
     * @param quantity 数量
     * @param txType 交易类型
     */
    private void updateStock(String warehouseCode, String partNo, BigDecimal quantity, String txType) {
        // 使用新的悲观锁更新方法替换原有逻辑
        tWarehouseStockService.updateStockWithPessimisticLock(warehouseCode, partNo, quantity, txType);
    }

    /**
     * 修改出入库单(头)
     * 
     * @param tWarehouseTransaction 出入库单(头)
     * @return 结果
     */
    @Override
    public int updateTWarehouseTransaction(TWarehouseTransaction tWarehouseTransaction)
    {
        return tWarehouseTransactionMapper.updateTWarehouseTransaction(tWarehouseTransaction);
    }

    /**
     * 批量删除出入库单(头)
     * 
     * @param txNos 需要删除的出入库单(头)主键
     * @return 结果
     */
    @Override
    public int deleteTWarehouseTransactionByTxNos(String[] txNos)
    {
        return tWarehouseTransactionMapper.deleteTWarehouseTransactionByTxNos(txNos);
    }

    /**
     * 删除出入库单(头)信息
     * 
     * @param txNo 出入库单(头)主键
     * @return 结果
     */
    @Override
    public int deleteTWarehouseTransactionByTxNo(String txNo)
    {
        return tWarehouseTransactionMapper.deleteTWarehouseTransactionByTxNo(txNo);
    }
}